home *** CD-ROM | disk | FTP | other *** search
- /*
-
- vgtek.c by Aaron Contorer 1987 for NCSA
- Copyright 1987, Board of Trustees, University of Illinois.
-
- Takes Tektronix codes as input; sends output to real graphics devices.
-
- CHANGES TO MAKE:
- Create a function to make sure a window is attached to a real window.
- Calling program will call this whenever switching between active windows.
- Pass virtual window number to RG driver so it can call back.
-
-
- */
-
- #define FALSE 0
- #define TRUE 1
- #define MAXVG 20 /* maximum number of VG windows */
-
- /* temporary states */
- #define HIY 0 /* waiting for various pieces of coordinates */
- #define EXTRA 1
- #define LOY 2
- #define HIX 3
- #define LOX 4
-
- #define DONE 5 /* not waiting for coordinates */
- #define ENTERVEC 6 /* entering vector mode */
-
- #define CANCEL 7 /* done but don't draw a line */
- #define RS 8 /* RS - incremental plot mode */
- #define ESCOUT 9 /* when you receive an escape char after a draw command */
- #define CMD0 50 /* got esc, need 1st cmd letter */
- #define SOMEL 51 /* got esc L, need 2nd letter */
- #define IGNORE 52 /* ignore next char */
- #define SOMEM 53 /* got esc M, need 2nd letter */
- #define IGNORE2 54
- #define INTEGER 60 /* waiting for 1st integer part */
- #define INTEGER1 61 /* waiting for 2nd integer part */
- #define INTEGER2 62 /* waiting for 3rd (last) integer part */
- #define COLORINT 70
- #define GTSIZE0 75
- #define GTSIZE1 76
- #define SOMET 80
- #define JUNKARRAY 81
- #define STARTDISC 82
- #define DISCARDING 83
-
- /* output modes */
- #define ALPHA 0
- #define DRAW 1
- #define MARK 3
- #define TEMPDRAW 101
- #define TEMPMOVE 102
- #define TEMPMARK 103
-
- /* stroked fonts */
- #define CHARWIDE 51 /* total horz. size */
- #define CHARTALL 76 /* total vert. size */
- #define CHARH 10 /* horz. unit size */
- #define CHARV 13 /* vert. unit size */
- #define LINE1 2969 /* cursor y for 1st text line */
-
- /* RG coordinate space dimensions */
- #define RGXSIZE 4096
- #define RGYSIZE 4096
-
- typedef struct {
- int
- (*init)(), (*point)(), (*drawline)(), (*newwin)(),
- (*clrscr)(), (*pagedone)(), (*dataline)(), (*pencolor)(),
- (*charmode)(), (*showcur)(), (*lockcur)(), (*hidecur)(),
- (*close)(), (*uncover)(), (*info)(),
- (*gmode)(), (*tmode)(), (*gin)();
- char *(*devname)();
- int (*bell)();
- } RGLINK;
-
- extern char *malloc();
- int donothing();
-
- struct VGWINTYPE {
- int RGdevice, RGnum;
- char mode,modesave; /* current output mode */
- char loy,hiy,lox,hix,ex,ey; /* current graphics coordinates */
- char nloy,nhiy,nlox,nhix,nex,ney; /* new coordinates */
- int curx,cury; /* current composite coordinates */
- int winbot,wintop,winleft,winright,wintall,winwide;
- /* position of window in virutal space */
- int textcol; /* text starts in 0 or 2048 */
- int intin; /* integer parameter being input */
- int pencolor; /* current pen color */
- int fontnum,charx,chary; /* char size */
- int count; /* for temporary use in special state loops */
- };
-
- #include <stdio.h>
- #include "vgtek.h"
- #include "vgfont.h"
- #include "tekstor.h"
-
- static struct VGWINTYPE VGwin[MAXVG]; /* virtual window descriptors */
- static char state[MAXVG],savstate[MAXVG];
- /* save state in a parallel array for speed */
- static STOREP VGstore[MAXVG]; /* the store where data for this widow is kept */
- static char storing[MAXVG]; /* are we currently saving data from this window */
- static int drawing[MAXVG]; /* redrawing or not? */
-
- #define NUMSIZES 6 /* number of char sizes */
- static int charxset[NUMSIZES] = {56,51,34,31,112,168};
- static int charyset[NUMSIZES] = {88,82,53,48,176,264};
-
- /*******************************************************************/
-
- static donothing()
- { }
-
-
- static fontnum(vw,n)
- int vw,n;
- /*
- Set font for window 'vw' to size 'n'.
- Sizes are 0..3 in Tek 4014 standard.
- Sizes 4 & 5 are used internally for Tek 4105 emulation.
- */
- {
- if (n<0 || n>=NUMSIZES) return(-1);
- VGwin[vw].fontnum=n;
- VGwin[vw].charx=charxset[n];
- VGwin[vw].chary=charyset[n];
- return(0);
- }
-
-
- static storexy(vw,x,y)
- int vw,x,y;
- /* set graphics x and y position */
- {
- VGwin[vw].curx = x;
- VGwin[vw].cury = y;
-
- #ifdef hmmm
- VGwin[vw].ex=x & 3;
- VGwin[vw].lox=(x >> 2) & 31;
- VGwin[vw].hix=(x >> 7) & 31;
- VGwin[vw].ey=y & 3;
- VGwin[vw].loy=(y >> 2) & 31;
- VGwin[vw].hiy=(y >> 7) & 31;
- #endif
- }
-
-
- static joinup(hi,lo,e)
- int hi,lo,e;
- /* returns the number represented by the 3 pieces */
- {
- return (((hi /* & 31 */ ) << 7) | ((lo /* & 31 */ ) << 2) | (e /* & 3 */));
- } /* end joinup() */
-
-
- static newcoord(vw)
- int vw;
- /*
- Replace x,y with nx,ny
- */
- {
- VGwin[vw].hiy = VGwin[vw].nhiy;
- VGwin[vw].hix = VGwin[vw].nhix;
- VGwin[vw].loy = VGwin[vw].nloy;
- VGwin[vw].lox = VGwin[vw].nlox;
- VGwin[vw].ey = VGwin[vw].ney;
- VGwin[vw].ex = VGwin[vw].nex;
-
- VGwin[vw].curx = joinup(VGwin[vw].nhix,VGwin[vw].nlox,VGwin[vw].nex);
- VGwin[vw].cury = joinup(VGwin[vw].nhiy,VGwin[vw].nloy,VGwin[vw].ney);
- }
-
-
- static linefeed(vw)
- /*
- Perform a linefeed & cr (CHARTALL units) in specified window.
- */
- {
- /* int y=joinup(VGwin[vw].hiy,VGwin[vw].loy,VGwin[vw].ey);*/
- int y=VGwin[vw].cury;
- int x;
-
- if (y>VGwin[vw].chary) y -= VGwin[vw].chary;
- else {
- y=3071 - VGwin[vw].chary;
- VGwin[vw].textcol = 2048 - VGwin[vw].textcol;
- }
- x = VGwin[vw].textcol;
- storexy(vw,x,y);
- }
-
-
- #ifdef DEBUG
- static drawc(vw,c)
- int vw;
- char c; /* character to draw */
- {
- putchar(c);
- }
- #else
- static drawc(vw,c)
- int vw;
- char c; /* character to draw */
- /*
- Draw a stroked character at the current cursor location.
- Uses simple 8-directional moving, 8-directional drawing.
- */
- {
- int x,y,savex,savey,strokex,strokey;
- int n; /* number of times to perform command */
- char *pstroke; /* pointer into stroke data */
- int hmag,vmag;
-
- if (c==10) {
- linefeed(vw);
- return(0);
- }
-
- if (c==7) {
- (*RG[VGwin[vw].RGdevice].bell) (VGwin[vw].RGnum);
- unstore(VGstore[vw]);
- return(0);
- }
-
- #ifdef oldm
- savey=y=joinup(VGwin[vw].hiy,VGwin[vw].loy,VGwin[vw].ey);
- savex=x=joinup(VGwin[vw].hix,VGwin[vw].lox,VGwin[vw].ex);
- #endif
- savey=y=VGwin[vw].cury;
- savex=x=VGwin[vw].curx;
-
- if (c==8) {
- if (savex<=VGwin[vw].textcol) return(0);
- savex -= VGwin[vw].charx;
- if (savex < VGwin[vw].textcol) savex = VGwin[vw].textcol;
- VGwin[vw].cury=savey;
- VGwin[vw].curx=savex;
- return(0);
- }
-
- hmag = VGwin[vw].charx / 10;
- vmag = VGwin[vw].chary / 10;
-
- if (3071 - savey < VGwin[vw].chary) {
- savey=y=3071-VGwin[vw].chary;
- }
-
- if (c<32 || c>126)
- return(0);
- c -= 32;
- pstroke = VGfont[c];
- while (*pstroke) {
- strokex=x;
- strokey=y;
- n = (*(pstroke++) - 48); /* run length */
- c = *(pstroke++); /* direction code */
-
- switch(c) { /* horizontal movement: positive = right */
- case 'e': case 'd': case 'c': case 'y': case 'h': case 'n':
- x += n * hmag;
- break;
-
- case 'q': case 'a': case 'z': case 'r': case 'f': case 'v':
- x -= n * hmag;
- }
-
- switch(c) { /* vertical movement: positive = up */
- case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
- y += n * vmag;
- break;
- case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
- y -= n * vmag;
- }
-
- switch(c) { /* draw or move */
- case 'r': case 't': case 'y': case 'f': case 'h':
- case 'v': case 'b': case 'n':
- clipvec (vw,strokex,strokey,x,y);
- break;
- }
-
- } /* end while not at end of string */
-
- /* Update cursor location to next char position */
- if (savex + 2 * VGwin[vw].chary <= 4096) savex += VGwin[vw].charx;
- else {
- savey -= VGwin[vw].chary;
- if (savey<0) {
- savey=3071 - VGwin[vw].chary;
- VGwin[vw].textcol = 2048 - VGwin[vw].textcol;
- }
- savex = VGwin[vw].textcol;
- }
-
- VGwin[vw].cury=savey;
- VGwin[vw].curx=savex;
-
- } /* end drawc() */
- #endif
-
- static clipt(p,q,t0,t1)
- float p,q,*t0,*t1;
- /* To be called only by clipvec() */
- {
- float r;
- int accept = TRUE;
-
- if (p<0.0) {
- r = q/p;
- if (r>*t1) accept = FALSE;
- else if (r>*t0) *t0 = r;
- }
- else if (p>0.0) {
- r = q/p;
- if (r<*t0) accept = FALSE;
- else if (r<*t1) *t1 = r;
- }
- else if (q<0.0) accept = FALSE;
- return(accept);
- }
-
- #ifdef DEBUG
- clipvec(vw,xa,ya,xb,yb)
- int vw;
- int xa,ya,xb,yb;
- {
- printf("%d,%d to %d,%d\n",xa,ya,xb,yb);
- }
- #else
- static clipvec(vw,xa,ya,xb,yb)
- int vw;
- int xa,ya,xb,yb;
-
- /*
- Draw a vector in vw's window from x0,y0 to x1,y1.
- Zoom the vector to the current visible window,
- and clip it before drawing it.
- Uses Liang-Barsky algorithm from ACM Transactions on Graphics,
- Vol. 3, No. 1, January 1984, p. 7.
- */
- {
- int t,b,l,r;
- float x0,y0,x1,y1,t0,t1,deltay,deltax;
- struct VGWINTYPE *vp;
- vp = &VGwin[vw];
-
- #ifdef otherway
- /* degenerate single points: do not draw */
- if (xa==xb && ya==yb) return;
- #endif
-
- t=vp->wintop;
- b=vp->winbot;
- l=vp->winleft;
- r=vp->winright;
-
- /* totally visible */
- if (xa<=r && xb<=r && xa>=l && xb>=l
- && ya<=t && yb<=t && ya>=b && yb>=b) {
- (*RG[vp->RGdevice].drawline) (vp->RGnum,
- (int) ((long)(xa - l) * RGXSIZE / vp->winwide),
- (int) ((long)(ya- b) * RGYSIZE / vp->wintall),
- (int) ((long)(xb - l) * RGXSIZE / vp->winwide),
- (int) ((long)(yb- b) * RGYSIZE / vp->wintall));
- return;
- }
-
- /* trivially invisible */
- if ((xa>r && xb>r) || (xa<l && xb<l)
- || (ya<b && yb<b) || (ya>t && yb>t)) {
- return;
- }
-
- /* the clipping algorithm */
- x0=(float) xa;
- y0=(float) ya;
- x1=(float) xb;
- y1=(float) yb;
-
- t0=0.0;
- t1=1.0;
- deltax = x1-x0;
-
- if(clipt(-deltax, x0 - l, &t0, &t1)) {
- if (clipt(deltax, r - x0, &t0, &t1)) {
- deltay = y1 - y0;
- if (clipt(-deltay, y0 - b, &t0, &t1)) {
- if (clipt(deltay, t - y0, &t0, &t1)) {
- if (t1<1.0) {
- x1 = x0 + t1*deltax;
- y1 = y0 + t1*deltay;
- }
- if (t0>0.0) {
- x0 += t0*deltax;
- y0 += t0*deltay;
- }
- /* draw the line, it is at least partially visible */
- (*RG[vp->RGdevice].drawline) (vp->RGnum,
- (int) ((long)((int)x0 - l) * RGXSIZE / vp->winwide),
- (int) ((long)((int)y0- b) * RGYSIZE / vp->wintall),
- (int) ((long)((int)x1 - l) * RGXSIZE / vp->winwide),
- (int) ((long)((int)y1- b) * RGYSIZE / vp->wintall));
-
- }
- }
- }
- } /* end if */
-
-
- } /* end clipvec() */
- #endif
-
- /*******************************************************
- ********************************************************
-
- All routines given below may be called by the user
- program. No routines given above may be called from
- the user program.
-
- ********************************************************
- *******************************************************/
-
-
- VGinit()
- /*
- Initialize the whole VG environment. Should be called ONCE
- at program startup before using the VG routines.
- */
- {
- int i;
- for (i=0; i<MAXVG; i++) {
- VGwin[i].RGdevice = -1; /* no device */
- }
- #ifndef DEBUG
- for (i=0; i<MAXRG; i++) { (*RG[i].init)(); }
- #endif
- }
-
-
- VGuncover(vw)
- /*
- Make sure window is completely visible, rather than partly or
- completely invisible.
- This function is to be called whenever a window is made active,
- to ensure that the user can see it.
- */
- {
- #ifndef DEBUG
- (*RG[VGwin[vw].RGdevice].uncover)(VGwin[vw].RGnum);
- #endif
- }
-
-
- VGdevice(vw,dev)
- int vw,dev;
- /*
- Detach window from its current device and attach it to the
- specified device. Returns negative number if unable to do so.
- Sample application: switching an image from #9 to Hercules.
- Must redraw after calling this.
- */
- {
- int newwin;
-
- newwin = (*RG[dev].newwin)();
- if (newwin<0) return(newwin); /* unable to open new window */
-
- (*RG[VGwin[vw].RGdevice].close)(VGwin[vw].RGnum);
- VGwin[vw].RGdevice = dev;
- VGwin[vw].RGnum = newwin;
- VGwin[vw].pencolor = 1;
- fontnum(vw,1);
- return(0);
- }
-
-
- VGnewwin(device)
- int device; /* number of RG device to use */
- /*
- Create a new VG window and return its number.
- New window will be attached to specified real device.
- Returns -1 if unable to create a new VG window.
- */
- {
- int vw=0;
- while (vw<MAXVG && VGwin[vw].RGdevice != -1) vw++;
- if (vw == MAXVG) {
- return(-1);
- }
- VGstore[vw] = newstore();
- if (VGstore[vw] == NULL) {
- return(-1); /* no memory */
- }
- VGwin[vw].RGdevice=device;
-
- VGwin[vw].RGnum = (*RG[device].newwin)();
- if (VGwin[vw].RGnum< 0) {
- /* no windows available on device */
- freestore(VGstore[vw]);
- return(-1);
- }
-
- VGwin[vw].mode=ALPHA;
- state[vw]=DONE;
- storing[vw]=TRUE;
- VGwin[vw].textcol=0;
- drawing[vw]=1;
- fontnum(vw,0);
- (*RG[device].pencolor)(VGwin[vw].RGnum,1);
-
- storexy(vw,0,3119);
- VGzoom(vw,0,0,4095,3119);
- return(vw);
- }
-
-
- VGclrstor(vw)
- int vw;
- /*
- Clear the store associated with window vw.
- All contents are lost.
- User program can call this whenever desired.
- Automatically called after receipt of Tek page command.
- */
- {
- freestore(VGstore[vw]);
- VGstore[vw] = newstore();
- /* Don't have to check for errors; there was definitely
- enough memory. */
- }
-
-
- VGdumpstore(vw,func)
- int vw;
- int (*func)();
- /*
- Successively call the function pointed to by 'func' for each
- character stored from window vw. Each character will
- be passed in integer form as the only parameter. A value of -1
- will be passed on the last call to indicate the end of the data.
- */
- {
- int data;
- STOREP st=VGstore[vw];
-
- topstore(st);
- while ((data=nextitem(st)) != -1) (*func)(data);
- (*func)(-1);
- }
-
-
- VGdraw(vw,c)
- int vw;
- char c; /* the latest input char */
- /*
- This is the main Tek emulator process. Pass it the window and
- the latest input character, and it will take care of the rest.
- Calls RG functions as well as local zoom and character drawing
- functions.
- */
- {
- char cmd;
- char value;
- char goagain; /* true means go thru the function a second time */
- struct VGWINTYPE *vp;
- vp = &VGwin[vw];
-
-
- /*** MAIN LOOP ***/
- do {
-
- cmd=(c >> 5) & 0x03;
- value=c & 0x1f;
- goagain=FALSE;
-
- switch(state[vw]) {
-
- case HIY: /* beginning of a vector */
- vp->nhiy = vp->hiy;
- vp->nhix = vp->hix;
- vp->nloy = vp->loy;
- vp->nlox = vp->lox;
- vp->ney = vp->ey;
- vp->nex = vp->ex;
-
- switch(cmd) {
- case 0:
- if (value == 27) { /* escape sequence */
- state[vw] = ESCOUT;
- savstate[vw] = HIY;
- }
- else if (value < 27) { /* ignore */
- break;
- }
- else {
- state[vw]=CANCEL;
- goagain=TRUE;
- }
- break;
- case 1: /* hiy */
- vp->nhiy=value;
- state[vw]=EXTRA;
- break;
- case 2: /* lox */
- vp->nlox=value;
- state[vw]=DONE;
- break;
- case 3: /* extra or loy */
- vp->nloy=value;
- state[vw]=LOY;
- break;
- }
- break;
-
- case ESCOUT:
- if (value != 13 && value != 10
- && value != 27 && value != '~') {/* skip all EOL-type characters */
- state[vw] = savstate[vw];
- goagain = TRUE;
- }
- break;
-
- case EXTRA: /* got hiy; expecting extra or loy */
- switch(cmd) {
- case 0:
- if (value == 27) { /* escape sequence */
- state[vw] = ESCOUT;
- savstate[vw] = EXTRA;
- }
- else if (value < 27) { /* ignore */
- break;
- }
- else {
- state[vw]=DONE;
- goagain=TRUE;
- }
- break;
- case 1: /* hix */
- vp->nhix=value;
- state[vw]=LOX;
- break;
- case 2: /* lox */
- vp->nlox=value;
- state[vw]=DONE;
- break;
- case 3: /* extra or loy */
- vp->nloy=value;
- state[vw]=LOY;
- break;
- }
- break;
-
- case LOY: /* got extra or loy; next may be loy or something else */
- switch(cmd) {
- case 0:
- if (value == 27) { /* escape sequence */
- state[vw] = ESCOUT;
- savstate[vw] = LOY;
- }
- else if (value < 27) { /* ignore */
- break;
- }
- else {
- state[vw]=DONE;
- goagain=TRUE;
- }
- break;
- case 1: /* hix */
- vp->nhix=value;
- state[vw]=LOX;
- break;
- case 2: /* lox */
- vp->nlox=value;
- state[vw]=DONE;
- break;
- case 3: /* this is loy; previous loy was really extra */
- vp->ney = (vp->nloy >> 2) & 3;
- vp->nex = (vp->nlox) & 3;
- vp->nloy=value;
- state[vw]=HIX;
- break;
- }
- break;
-
- case HIX: /* hix or lox */
- switch(cmd) {
- case 0:
- if (value == 27) { /* escape sequence */
- state[vw] = ESCOUT;
- savstate[vw] = HIX;
- }
- else if (value < 27) { /* ignore */
- break;
- }
- else {
- state[vw]=DONE;
- goagain=TRUE;
- }
- break;
- case 1: /* hix */
- vp->nhix=value;
- state[vw]=LOX;
- break;
- case 2: /* lox */
- vp->nlox=value;
- state[vw]=DONE;
- break;
- }
- break;
-
- case LOX: /* must be lox */
- switch(cmd) {
- case 0:
- if (value == 27) { /* escape sequence */
- state[vw] = ESCOUT;
- savstate[vw] = LOX;
- }
- else if (value < 27) { /* ignore */
- break;
- }
- else {
- state[vw]=DONE;
- goagain=TRUE;
- }
- break;
- case 2:
- vp->nlox=value;
- state[vw]=DONE;
- break;
- }
- break;
-
- case ENTERVEC:
- if (c==7) vp->mode = DRAW;
- if (c < 27)
- break;
- state[vw] = HIY;
- vp->mode = TEMPMOVE;
- vp->modesave = DRAW;
- goagain = TRUE;
- break;
-
- case RS:
- switch (c) {
- case ' ': /* pen up */
- vp->modesave = vp->mode;
- vp->mode = TEMPMOVE;
- break;
- case 'P': /* pen down */
- vp->mode = DRAW;
- break;
- case 'D': /* move up */
- vp->cury++;
- break;
- case 'E':
- vp->cury++;
- vp->curx++;
- break;
- case 'A':
- vp->curx++;
- break;
- case 'I':
- vp->curx++;
- vp->cury--;
- break;
- case 'H':
- vp->cury--;
- break;
- case 'J':
- vp->curx--;
- vp->cury--;
- break;
- case 'B':
- vp->curx--;
- break;
- case 'F':
- vp->cury++;
- vp->curx--;
- break;
- case 27:
- savstate[vw] = RS;
- state[vw] = ESCOUT;
- break;
-
- default:
- /* storexy(vw,vp->curx,vp->cury);*/
- state[vw] = CANCEL;
- goagain = TRUE;
- break;
- }
- if (vp->mode == DRAW)
- clipvec(vw,vp->curx,vp->cury,vp->curx,vp->cury);
- #ifdef DEBUG
- printf("RS: %d,%d\n",vp->curx,vp->cury);
- #endif
- break;
-
- case CMD0: /* get 1st letter of cmd */
- switch(c) {
- case 29: /* GS, start draw */
- state[vw] = DONE;
- goagain = TRUE;
- break;
- case '8':
- fontnum(vw,0);
- state[vw]=DONE;
- break;
- case '9':
- fontnum(vw,1);
- state[vw]=DONE;
- break;
- case ':':
- fontnum(vw,2);
- state[vw]=DONE;
- break;
- case ';':
- fontnum(vw,3);
- state[vw]=DONE;
- break;
- case 12: /* form feed = clrscr */
- VGpage(vw);
- VGclrstor(vw);
- break;
- case 'L':
- state[vw] = SOMEL;
- break;
- case 'K':
- state[vw] = IGNORE;
- break;
- case 'M':
- state[vw] = SOMEM;
- break;
- case 'T':
- state[vw] = SOMET;
- break;
- case 26:
- (*RG[vp->RGdevice].gin)(vp->RGnum);
- unstore(VGstore[vw]);
- unstore(VGstore[vw]);
- break;
- case 10:
- case 13:
- case 27:
- case '~':
- savstate[vw] = DONE;
- state[vw] = ESCOUT;
- break; /* completely ignore these after ESC */
- default:
- state[vw] = DONE;
- } /* end switch */
- break;
-
- case SOMET:
- /* Got ESC T; now handle 3rd char. */
- switch(c) {
- case 'G': /* set surface color map */
- state[vw]=INTEGER;
- savstate[vw]=JUNKARRAY;
- break;
- case 'F': /* set dialog area color map */
- state[vw]=JUNKARRAY;
- break;
- default:
- state[vw]=DONE;
- }
- break;
-
- case JUNKARRAY:
- /* This character is the beginning of an integer array
- to be discarded. Get array size. */
- savstate[vw]=STARTDISC;
- state[vw]=INTEGER;
- break;
-
- case STARTDISC:
- /* Begin discarding integers. */
- vp->count = vp->intin + 1;
- goagain=TRUE;
- state[vw]=DISCARDING;
- break;
-
- case DISCARDING:
- /* We are in the process of discarding an integer array. */
- goagain=TRUE;
- if (!(--(vp->count))) state[vw]=DONE;
- else if (vp->count==1) {
- state[vw]=INTEGER;
- savstate[vw]=DONE;
- } else {
- state[vw]=INTEGER;
- savstate[vw]=DISCARDING;
- }
- break;
-
- case INTEGER:
- if (c & 0x40) {
- vp->intin = c & 0x3f;
- state[vw] = INTEGER1;
- } else {
- vp->intin = c & 0x0f;
- if (!(c & 0x10)) vp->intin *= -1;
- state[vw] = savstate[vw];
- }
- break;
-
- case INTEGER1:
- if (c & 0x40) {
- vp->intin = (vp->intin << 6) | (c & 0x3f);
- state[vw] = INTEGER2;
- } else {
- vp->intin = (vp->intin << 4) | (c & 0x0f);
- if (!(c & 0x10)) vp->intin *= -1;
- state[vw] = savstate[vw];
- }
- break;
-
- case INTEGER2:
- vp->intin = (vp->intin << 4) | (c & 0x0f);
- if (!(c & 0x10)) vp->intin *= -1;
- state[vw] = savstate[vw];
- break;
-
- case IGNORE: /* ignore next char; it's not supported */
- state[vw]=DONE;
- break;
-
- case IGNORE2: /* ignore next 2 chars */
- state[vw]=IGNORE;
- break;
-
- case SOMEL: /* now process 2nd letter */
- switch(c) {
- case 'F': /* move */
- vp->modesave = vp->mode;
- vp->mode = TEMPMOVE;
- state[vw] = HIY;
- break;
- case 'G': /* draw */
- vp->modesave = vp->mode;
- vp->mode = TEMPDRAW;
- state[vw] = HIY;
- break;
- case 'H': /* marker */
- vp->modesave = vp->mode;
- vp->mode = TEMPMARK;
- state[vw] = HIY;
- break;
- default:
- state[vw]=DONE;
- } /* end switch */
- break;
-
- case SOMEM:
- switch(c) {
- case 'C': /* set graphtext size */
- savstate[vw]=GTSIZE0;
- state[vw]=INTEGER;
- break;
- case 'L': /* set line index */
- savstate[vw]=COLORINT;
- state[vw]=INTEGER;
- break;
- default:
- state[vw]=DONE;
- } /* end switch */
- break;
-
- case COLORINT: /* set line index; have integer */
- vp->pencolor=vp->intin;
- (*RG[vp->RGdevice].pencolor)
- (vp->RGnum,vp->intin);
- state[vw]=DONE;
- goagain=TRUE; /* we ignored current char; now process it */
- break;
-
- case GTSIZE0:
- /* discard the first integer; get the 2nd */
- state[vw]=INTEGER; /* get the important middle integer */
- savstate[vw]=GTSIZE1;
- goagain=TRUE;
- break;
-
- case GTSIZE1:
- /* integer is the height */
- if (vp->intin < 88) fontnum(vw,0);
- else if (vp->intin < 149) fontnum(vw,4);
- else fontnum(vw,5);
- state[vw]=INTEGER; /* discard last integer */
- savstate[vw]=DONE;
- goagain=TRUE;
- break;
-
- case DONE: /* ready for anything */
- switch(c) {
- case 31:
- vp->mode=ALPHA;
- state[vw]=CANCEL;
- break;
- case 30:
- state[vw]=RS;
- break;
- case 28:
- if (cmd) {
- vp->mode=MARK;
- state[vw]=HIY;
- }
- break;
- case 29:
- state[vw]=ENTERVEC;
- break;
- case 27:
- state[vw]=CMD0;
- break;
- default:
- if (vp->mode==ALPHA) {
- drawc(vw,c);
- state[vw]=CANCEL;
- }
- else if (vp->mode==DRAW && cmd) {
- state[vw]=HIY;
- goagain=TRUE;
- }
- else if (vp->mode==MARK && cmd) {
- state[vw]=HIY;
- goagain=TRUE;
- }
- else
- state[vw] = CANCEL; /* do nothing */
- } /* end switch(c) */
- } /* end switch(state) */
-
- if (state[vw]==DONE) {
- if (vp->mode==TEMPMOVE) {
- vp->mode=vp->modesave;
- newcoord(vw);
- }
- else if (vp->mode==DRAW || vp->mode==TEMPDRAW) {
- #ifdef oldm
- clipvec(vw,
- joinup(vp->hix,vp->lox,vp->ex),
- joinup(vp->hiy,vp->loy,vp->ey),
- joinup(vp->nhix,vp->nlox,vp->nex),
- joinup(vp->nhiy,vp->nloy,vp->ney));
- #endif
- clipvec(vw,vp->curx,vp->cury,
- joinup(vp->nhix,vp->nlox,vp->nex),
- joinup(vp->nhiy,vp->nloy,vp->ney));
-
- if (vp->mode==TEMPDRAW) vp->mode=vp->modesave;
- newcoord(vw);
- }
- else if (vp->mode==MARK || vp->mode==TEMPMARK) {
- /* draw marker */
- newcoord(vw);
- }
- } /* end if done */
-
- if (state[vw]==CANCEL) state[vw]=DONE;
-
- } while (goagain);
- /*** END OF MAIN LOOP ***/
-
- } /* end VGdraw() */
-
-
- VGpage(vw)
- int vw;
- /* Clear screen and have a few other effects:
- - Return graphics to home position (0,3071)
- - Switch to alpha mode
- This is a standard Tek command; don't look at me.
- */
- {
- #ifndef DEBUG
- (*RG[VGwin[vw].RGdevice].clrscr)(VGwin[vw].RGnum);
- (*RG[VGwin[vw].RGdevice].pencolor)(VGwin[vw].RGnum,1);
- #endif
- VGwin[vw].mode=ALPHA;
- state[vw] = DONE;
- VGwin[vw].textcol=0;
- fontnum(vw,0);
- storexy(vw,0,3071);
- } /* end page */
-
-
- VGpred(vw,dest)
- int vw,dest;
- /*
- Redraw window 'vw' in pieces to window 'dest'.
- Must call this function repeatedly to draw whole image.
- Only draws part of the image at a time, to yield CPU power.
- Returns 0 if needs to be called more, or 1 if the image
- is complete. Another call would result in the redraw beginning again.
- User should clear screen before beginning redraw.
- */
- {
- int data;
- STOREP st=VGstore[vw];
- int count=0;
-
- if (drawing[vw]) { /* wasn't redrawing */
- topstore(st);
- drawing[vw] = 0; /* redraw incomplete */
- }
-
- while ( ++count < PREDCOUNT && ((data=nextitem(st)) != -1) ) {
- VGdraw(dest,data);
- }
-
- if (data == -1) drawing[vw] = 1; /* redraw complete */
- return(drawing[vw]);
- }
-
-
- VGstopred(vw,dest)
- /*
- Abort VGpred redrawing of specified window.
- Must call this routine if you decide not to complete the redraw.
- */
- {
- drawing[vw]=1;
- }
-
-
- VGredraw(vw,dest)
- int vw,dest;
- /*
- Redraw the contents of window 'vw' to window 'dest'.
- Does not yield CPU until done.
- User should clear the screen before calling this, to avoid
- a messy display.
- */
- {
- int data;
- STOREP st=VGstore[vw];
-
- topstore(st);
- while ((data=nextitem(st)) != -1) {
- VGdraw(dest,data);
- }
- }
-
-
- VGzoom(vw,x0,y0,x1,y1)
- /*
- Set new borders for zoom/pan region.
- x0,y0 is lower left; x1,y1 is upper right.
- User should redraw after calling this.
- */
- {
- VGwin[vw].winbot=y0;
- VGwin[vw].winleft=x0;
- VGwin[vw].wintop=y1;
- VGwin[vw].winright=x1;
- VGwin[vw].wintall = y1-y0+1;
- VGwin[vw].winwide = x1-x0+1;
- VGgiveinfo(vw);
- }
-
-
- VGzcpy(src,dest)
- /*
- Set zoom/pan borders for window 'dest' equal to those for window 'src'.
- User should redraw window 'dest' after calling this.
- */
- {
- VGzoom(dest,VGwin[src].winleft, VGwin[src].winbot,
- VGwin[src].winright, VGwin[src].wintop);
- }
-
-
- VGclose(vw)
- /*
- Close virtual window.
- Release its real graphics device and its store.
- */
- {
- (*RG[VGwin[vw].RGdevice].close)(VGwin[vw].RGnum);
- freestore(VGstore[vw]);
- VGwin[vw].RGdevice = -1;
- }
-
-
- VGwrite(vw,data,count)
- int vw, count;
- char *data;
- /*
- Draw the data pointed to by 'data' of length 'count'
- on window vw, and add it to the store for that window.
- This is THE way for user program to pass Tektronix data.
- */
- {
- char *c = data;
- char *end = &(data[count]);
-
- if (VGwin[vw].RGdevice == -1 || vw >= MAXVG || vw < 0) return(-1);
- /* window not open */
-
- if (storing[vw]) {
- while (c != end) {
- addstore(VGstore[vw], *c);
- VGdraw(vw,*c++);
- }
- } else {
- while (c != end) VGdraw(vw,*c++);
- }
- return(0);
- }
-
-
- VGgiveinfo(vw)
- int vw;
- /*
- Send interesting information about the virtual window down to
- its RG, so that the RG can make VG calls and display zoom values
- */
- {
- (*RG[VGwin[vw].RGdevice].info)(VGwin[vw].RGnum,
- vw,
- VGwin[vw].winbot,
- VGwin[vw].winleft,
- VGwin[vw].wintop,
- VGwin[vw].winright);
- }
-
-
- char *
- VGrgname(rgdev)
- int rgdev;
- /*
- Return a pointer to a human-readable string
- which describes the specified real device
- */
- {
- return(*RG[rgdev].devname)();
- }
-
-
- VGgmode(rgdev)
- int rgdev;
- /* Put the specified real device into graphics mode */
- {
- #ifndef DEBUG
- (*RG[rgdev].gmode)();
- #endif
- }
-
-
- VGtmode(rgdev)
- int rgdev;
- /* Put the specified real device into text mode */
- {
- (*RG[rgdev].tmode)();
- }
-
-
- VGgindata(vw,x,y,c,a)
- int vw,x,y;
- char c;
- char *a;
- /*
- Translate data for output as GIN report.
-
- User indicates VW number and x,y coordinates of the GIN cursor.
- Coordinate space is 0-4095, 0-4095 with 0,0 at the bottom left of
- the real window and 4095,4095 at the upper right of the real window.
- 'c' is the character to be returned as the keypress.
- 'a' is a pointer to an array of 5 characters. The 5 chars must
- be transmitted by the user to the remote host as the GIN report.
- */
- {
- long x2,y2;
-
- x2 = ((x * VGwin[vw].winwide) / RGXSIZE + VGwin[vw].winleft) >> 2;
- y2 = ((y * VGwin[vw].wintall) / RGYSIZE + VGwin[vw].winbot) >> 2;
-
- a[0] = c;
- a[1] = 0x20 | ((x2 & 0x03E0) >> 5);
- a[2] = 0x20 | (x2 & 0x001F);
- a[3] = 0x20 | ((y2 & 0x03E0) >> 5);
- a[4] = 0x20 | (y2 & 0x001F);
- }
-